package com.example.shiro_springboot.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.example.shiro_springboot.matcher.RetryLimitHashedCredentialsMatcher;
import com.example.shiro_springboot.realm.MyRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.io.InputStream;

@Configuration
public class ShiroConfig {

    @Autowired
    private MyRealm myRealm;
    @Autowired
    private RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher;

    // SecurityManager容器
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置登录MD5认证
//        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//        matcher.setHashAlgorithmName("md5");// 设置加密算法
//        matcher.setHashIterations(2);// 设置加密迭代次数
//        myRealm.setCredentialsMatcher(matcher);
        retryLimitHashedCredentialsMatcher.setHashAlgorithmName("md5");
        retryLimitHashedCredentialsMatcher.setHashIterations(2);
        myRealm.setCredentialsMatcher(retryLimitHashedCredentialsMatcher);
        securityManager.setRealm(myRealm);
//        // 也可设置多个realm验证
//        ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
//        // AllSuccessfulStrategy 所有验证realm都要成功
//        // AtLeastOneSuccessfulStrategy  至少一个成功 （默认）
//        // FirstSuccessfulStrategy   第一个成功
//        modularRealmAuthenticator.setAuthenticationStrategy(new AllSuccessfulStrategy());
//        securityManager.setAuthenticator(modularRealmAuthenticator);
//        List<Realm>  realms = new ArrayList<>();
//        realms.add(realm1);
//        realms.add(realm2);
//        securityManager.setRealms(realms);

        // 设置remember me
        securityManager.setRememberMeManager(cookieRememberMeManager());
        // 设置ehcache
        // 添加ehcache后，只在第一次完成授权即可，后续直接从ehcache中获取权限，不会每次都调用Realm#doGetAuthorizationInfo的方法
        securityManager.setCacheManager(cacheManager());
        return securityManager;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        // 配置顺序  注意****
        definition.addPathDefinition("/login", "anon");// 不认证也可以访问
        definition.addPathDefinition("/userLogin", "anon");
        // 登出方法有shiro完成，只需要配置登录的拦截器即可
        definition.addPathDefinition("/logout", "logout");// 登出
        definition.addPathDefinition("/**", "user");// 需要已登录或“记住我”的用户才能访问

        return definition;
    }

    // 设置RememberMeManager对象
    public CookieRememberMeManager cookieRememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        // 设置cookie参数
        cookieRememberMeManager.setCookie(setCookie());
        // cookie加密
        cookieRememberMeManager.setCipherKey("1234567890abcdef".getBytes());
        return cookieRememberMeManager;
    }

    // 设置Cookie
    public SimpleCookie setCookie() {
        SimpleCookie cookie = new SimpleCookie();
//        cookie.setDomain(domain);   跨域   多个模块之间cookie共享
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(30 * 24 * 60 * 60);
        cookie.setName("zhangjq");
        return cookie;
    }

    /**
     * shiro整合thymeleaf授权
     * 前端验证
     * 与shiro验证一样，会调用Realm的doGetAuthorizationInfo的授权方法
     *
     * @return
     */
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

    /**
     * 配置shiro整合ehcache
     * 将CacheManager放入到securityManager中
     */
    @Bean
    public EhCacheManager cacheManager() {
        // shiro的cacheManager
        EhCacheManager cacheManager = new EhCacheManager();
        // Ehcache的cacheManager
        InputStream inputStream = null;
        try {
            inputStream = ResourceUtils.getInputStreamForPath("classpath:ehcache/shiro-ehcache.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        net.sf.ehcache.CacheManager ehCacheManager = new net.sf.ehcache.CacheManager(inputStream);
        // 将Ehcache的cacheManager对象存储到shiro的cacheManager对象中
        cacheManager.setCacheManager(ehCacheManager);
        return cacheManager;
    }
}
